package nodex

import (
	"context"
	"gitee.com/zhongguo168a/gocodes/datax"
	"gitee.com/zhongguo168a/gocodes/myx/errorx"
	"sync"
)

/**
所有的rpc集合
*/
var rpcs = &sync.Map{}

func RemoveChanRPC(name string, ident string) (err error) {
	_, has := n.config.ChanRPCSelectors[name]
	if has == false {
		return errorx.New("rpc selector not found", datax.M{"routePath": name, "ident": ident})
	}
	id := name
	if ident != "" {
		id += "_" + ident
	}
	rpcs.Delete(id)
	return
}

// CreateRPC 创建 chanrpc
// 通常用于有队列需求的服务，例如一个玩家一个chanrpc，玩家的协议就可以根据玩家的协议队列顺序处理
// 如果已经存在，则返回
func CreateChanRPC(name string, ident string) (chanrpc IChanRPC, err error) {
	_, has := n.config.ChanRPCSelectors[name]
	if has == false {
		return nil, errorx.New("chanrpc selector not found", datax.M{"chanrpc": name, "ident": ident})
	}
	rpc, ok := rpcs.Load(ident)
	if ok {
		return rpc.(IChanRPC), nil
	}
	return createChanRPC(name, ident)
}

type MiddleFunc func(ctx IContext, oldreply interface{}, olderr error) (newreply interface{}, newerr error)

func createChanRPC(name string, ident string) (chanrpc IChanRPC, err error) {
	rpc := newRPC(name, ident, n.config.ChanRPCSelectors[name])
	rpcs.Store(ident, rpc)

	routes := n.getRouteByRPC(name)
	for _, val := range routes {
		routeConf := val.Config
		route := val
		if route.ReturnNum == 0 { //  无返回值
			rpc.server.Register(routeConf.Path, func(args []interface{}) {
				a0 := args[0].(context.Context)
				a1 := args[1]
				route.Call(a0, a1, nil)
				return
			})
		} else {
			rpc.server.Register(routeConf.Path, func(args []interface{}) (result interface{}) {
				a0 := args[0].(context.Context)
				a1 := args[1]
				a2 := args[2]
				result = route.Call(a0, a1, a2)
				return
			})
		}
	}

	go rpc.Run()
	return rpc, nil
}

type IValid interface {
	Valid() error
}

func (n *Node) getRouteByRPC(chanrpcName string) (r []*Router) {
	for _, val := range n.routeMap {
		if val.Config.ChanRPC == chanrpcName {
			r = append(r, val)
		}
	}

	return
}

func GetChanRPC(ident string) IChanRPC {
	srv, ok := rpcs.Load(ident)
	if ok == false {
		return nil
	}
	return srv.(IChanRPC)
}
